﻿using System;
using System.Collections.Generic;

namespace Patterns.Builder {

    public class AbstractExample {

        public static void Run() {
            // Create director and builders
            Director director = new Director();

            Builder b1 = new ConcreteBuilder1();
            Builder b2 = new ConcreteBuilder2();

            // Construct two products
            director.Construct(b1);
            Product p1 = b1.GetResult();
            p1.Show();

            director.Construct(b2);
            Product p2 = b2.GetResult();
            p2.Show();
        }

        // "Director"
        private class Director {
            // Builder uses a complex series of steps
            public void Construct(Builder builder) {
                builder.BuildPartA();
                builder.BuildPartB();
            }
        }

        // "Builder"
        private abstract class Builder {
            public abstract void BuildPartA();
            public abstract void BuildPartB();
            public abstract Product GetResult();
        }

        // "ConcreteBuilder1"
        private class ConcreteBuilder1 : Builder {
            private Product product = new Product();

            public override void BuildPartA() {
                product.Add("PartA");
            }

            public override void BuildPartB() {
                product.Add("PartB");
            }

            public override Product GetResult() {
                return product;
            }
        }

        // "ConcreteBuilder2"
        private class ConcreteBuilder2 : Builder {
            private Product product = new Product();

            public override void BuildPartA() {
                product.Add("PartX");
            }

            public override void BuildPartB() {
                product.Add("PartY");
            }

            public override Product GetResult() {
                return product;
            }
        }

        // "Product"
        private class Product {
            List<string> parts = new List<string>();

            public void Add(string part) {
                parts.Add(part);
            }

            public void Show() {
                Console.WriteLine("\nProduct Parts -------");
                parts.ForEach(part =>
                    Console.WriteLine(part));
            }
        }
    }
}
